MCP 서버가 작동하게 되었으니, 이제 클라이언트 쪽을 구축할 차례입니다. 클라이언트는 애플리케이션 코드가 MCP 서버와 통신하고 그 기능에 접근할 수 있게 해주는 것입니다.
클라이언트 아키텍처 이해하기
대부분의 실제 프로젝트에서는 MCP 클라이언트 또는 MCP 서버 중 하나만 구현하게 됩니다 - 둘 다는 아닙니다. 이 프로젝트에서는 둘이 어떻게 함께 작동하는지 볼 수 있도록 둘 다 구축하고 있습니다.
MCP 클라이언트는 두 가지 주요 구성 요소로 이루어져 있습니다:
- MCP Client - 세션 사용을 더 쉽게 만들기 위해 우리가 만드는 커스텀 클래스
- Client Session - 서버에 대한 실제 연결 (MCP Python SDK의 일부)
클라이언트 세션은 신중한 리소스 관리가 필요합니다 - 작업이 끝나면 연결을 올바르게 정리해야 합니다. 그래서 모든 정리를 자동으로 처리하는 자체 클래스로 감싸는 것입니다.
클라이언트가 애플리케이션에 어떻게 맞는가
애플리케이션 흐름 다이어그램을 기억하시나요? 클라이언트는 두 가지 핵심 지점에서 코드가 MCP 서버와 상호작용할 수 있게 해주는 것입니다:
CLI 코드는 클라이언트를 사용하여:
- Claude에게 보낼 사용 가능한 도구 목록을 가져옵니다
- Claude가 요청할 때 도구를 실행합니다
핵심 클라이언트 함수 구현하기
두 가지 필수 함수를 구현해야 합니다: list_tools()와 call_tool().
도구 목록 함수
이 함수는 MCP 서버에서 사용 가능한 모든 도구를 가져옵니다:
async def list_tools(self) -> list[types.Tool]:
result = await self.session().list_tools()
return result.tools
간단합니다 - 세션(서버에 대한 연결)에 접근하고, 내장된 list_tools() 메서드를 호출하며, 결과에서 도구를 반환합니다.
도구 호출 함수
이 함수는 서버에서 특정 도구를 실행합니다:
async def call_tool(
self, tool_name: str, tool_input: dict
) -> types.CallToolResult | None:
return await self.session().call_tool(tool_name, tool_input)
도구 이름과 입력 매개변수(Claude가 제공)를 서버에 전달하고 결과를 반환합니다.
클라이언트 테스트하기
클라이언트 파일 하단에 간단한 테스트 하네스가 포함되어 있습니다. 직접 실행하여 모든 것이 작동하는지 확인할 수 있습니다:
uv run mcp_client.py
이렇게 하면 MCP 서버에 연결하고 사용 가능한 도구를 출력합니다. 설명과 입력 스키마를 포함한 도구 정의가 표시되는 것을 볼 수 있습니다.
모든 것을 합치기
클라이언트 함수가 구현되면 메인 애플리케이션을 실행하여 전체 흐름을 테스트할 수 있습니다:
uv run main.py
"report.pdf 문서의 내용은 무엇인가요?"라고 질문해 보세요.
뒤에서 일어나는 일은 다음과 같습니다:
- 애플리케이션이 클라이언트를 사용하여 사용 가능한 도구를 가져옵니다
- 이러한 도구가 질문과 함께 Claude에게 전송됩니다
- Claude가 read_doc_contents 도구를 사용하기로 결정합니다
- 애플리케이션이 클라이언트를 사용하여 해당 도구를 실행합니다
- 결과가 Claude에게 반환되고, Claude가 여러분에게 응답합니다
클라이언트는 애플리케이션 로직과 MCP 서버의 기능 사이의 브리지 역할을 하여, 강력한 도구를 AI 워크플로에 쉽게 통합할 수 있게 해줍니다.